package errcode

import "fmt"

// ErrorCode 错误码结构
type ErrorCode struct {
	Code     int    `json:"code"`
	Message  string `json:"message"`
	HTTPCode int    `json:"-"` // 对应的HTTP状态码
}

// Error 实现 error 接口
func (e ErrorCode) Error() string {
	return fmt.Sprintf("code: %d, message: %s", e.Code, e.Message)
}

// WithMessage 自定义错误消息
func (e ErrorCode) WithMessage(msg string) ErrorCode {
	newErr := e
	newErr.Message = msg
	return newErr
}

// WithMessagef 格式化错误消息
func (e ErrorCode) WithMessagef(format string, args ...interface{}) ErrorCode {
	return e.WithMessage(fmt.Sprintf(format, args...))
}

// wrappedError 包装原始错误和错误码
type wrappedError struct {
	ec  ErrorCode
	err error
}

// Error 实现 error 接口
func (w *wrappedError) Error() string {
	if w.err != nil {
		return fmt.Sprintf("%s: %v", w.ec.Error(), w.err)
	}
	return w.ec.Error()
}

// Unwrap 实现 errors.Unwrap 接口，支持 errors.Is 和 errors.As
func (w *wrappedError) Unwrap() error {
	return w.err
}

// As 实现 errors.As 接口，支持提取 ErrorCode
func (w *wrappedError) As(target interface{}) bool {
	if ec, ok := target.(*ErrorCode); ok {
		*ec = w.ec
		return true
	}
	return false
}

// Wrap 包装原始错误，保留堆栈信息
// 用法: return errcode.Wrap(err, errcode.DatabaseError)
func Wrap(err error, ec ErrorCode) error {
	if err == nil {
		return ec
	}
	return &wrappedError{
		ec:  ec,
		err: err,
	}
}

// Wrapf 包装原始错误并格式化消息
// 用法: return errcode.Wrapf(err, errcode.DatabaseError, "failed to create area %s", name)
func Wrapf(err error, ec ErrorCode, format string, args ...interface{}) error {
	if err == nil {
		return ec.WithMessagef(format, args...)
	}
	return &wrappedError{
		ec:  ec.WithMessagef(format, args...),
		err: err,
	}
}
